package tcp_proxy_middleware

import (
	"fmt"

	"gin-gateway/core/log"
	"github.com/afex/hystrix-go/hystrix"
	"gin-gateway/reverse_proxy"
)

func TcpCircuitBreakMiddleware() func(c *reverse_proxy.TcpSliceRouterContext) {
	return func(c *reverse_proxy.TcpSliceRouterContext) {
		serviceDetail := GetServiceDetail(c)

		if serviceDetail.CircuitConfig.NeedCircuit == 1 {
			err := hystrix.Do(serviceDetail.Info.ServiceName, func() (err error) {
				defer func() {
					// 通过捕获 panic 来感知下游 lb 地址为空或者连接失败，
					// 连接关闭不在这里处理，
					// 而且对于 tcp 长连接要给 hystrix 配置超长的 timeout 时间
					if e := recover(); e != nil {
						remoteAddr := c.Conn.RemoteAddr().String()
						log.Error("tcp: panic serving %v: %v", remoteAddr, e)
						fmt.Println("hystrix panic<<<<<")
						err = fmt.Errorf("%v", e)
					}
				}()

				c.Next()

				return
			}, func(err error) error {
				if err != nil {
					fmt.Println("hystrix error<<<<<", err)
					_, err := c.Conn.Write([]byte("error closed"))
					if err != nil {
						log.Error("TcpCircuitBreakMiddleware Write err :", err.Error())
						return err
					}
					return nil
				}
				return nil
			})
			if err != nil {
				log.Error("tcp: error serving %v: %v", serviceDetail.Info.ServiceName, err)
				return
			}
			return
		}
		c.Next()
	}
}
